package GPSChallenge.juego;

import java.io.File;

import java.io.FileOutputStream;

import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

import Excepciones.NoConozcoAlObstaculoException;
import Excepciones.NoConozcoAlVehiculoException;
import Excepciones.NoConozcoLaBanderaException;
import Excepciones.NoConozcoLaSorpresaException;
import GPSChallenge.Ciudad;
import GPSChallenge.Jugador;
import GPSChallenge.bandera.Bandera;
import GPSChallenge.movimiento.Abajo;
import GPSChallenge.movimiento.Arriba;
import GPSChallenge.movimiento.ContadorDeMovimientos;
import GPSChallenge.movimiento.Derecha;
import GPSChallenge.movimiento.Izquierda;
import GPSChallenge.movimiento.Posicion;
import GPSChallenge.obstaculo.Obstaculo;
import GPSChallenge.sorpresa.Sorpresa;
import GPSChallenge.vehiculo.Auto;
import GPSChallenge.vehiculo.Camioneta4x4;
import GPSChallenge.vehiculo.Estado;
import GPSChallenge.vehiculo.Moto;
import GPSChallenge.vehiculo.Vehiculo;

import org.jdom2.*;

public abstract class Juego {
	
	protected Ciudad ciudad;
	
	protected Jugador jugador;
	
	protected Vehiculo vehiculo;
	
	public void Serializar(){
		Document doc = ciudad.Serializar();
		try{
			
			XMLOutputter xmlOutput= new XMLOutputter(Format.getPrettyFormat());
			
			xmlOutput.output(doc, new FileOutputStream(new File("./src/ciudadGuardada.xml")));
			
			}
			catch (Exception ex){
				ex.printStackTrace();
			}
		
		Document doc1 = new Document();
		Element juego = new Element("juego");
		juego.setAttribute("movimientosHechos",String.valueOf(ContadorDeMovimientos.obtenerInstancia().obtenerCantidadDeMovimientosHechos()));
		juego.addContent(vehiculo.Serializar());
		juego.addContent(jugador.Serializar());
		doc1.setRootElement(juego);
		try{
			
			XMLOutputter xmlOutput= new XMLOutputter(Format.getPrettyFormat());
			
			xmlOutput.output(doc1, new FileOutputStream(new File("./src/juegoGuardado.xml")));
			
			}
			catch (Exception ex){
				ex.printStackTrace();
			}
		
	}
	
	public Estado obtenerEstadoDeUnVehiculo(String estado){
		Estado vehiculo =null;
		if (estado.equals("Moto")){
			vehiculo=Moto.obtenerEstado();
		}
		if(estado.equals("4x4")){
			vehiculo=Camioneta4x4.obtenerEstado();
		}
		if(estado.equals("Auto")){
			vehiculo=Auto.obtenerEstado();
		}
		return vehiculo;
		
	}
	
	public String obtenerNombreDeJugador(){
		
		return (this.jugador.obtenerNombre());
		
	}
	
	public Estado obtenerEstadoDelVehiculo(){
		
		return (this.vehiculo.obtenerEstado());
		
	}
	
	public Vehiculo obtenerVehiculo(){
		
		return vehiculo;
	}
	
	public abstract int obtenerPuntajeDeJugador();
	
	public int obtenerCantidadDeMovimientosHechos(){
		
		return (ContadorDeMovimientos.obtenerInstancia().obtenerCantidadDeMovimientosHechos());
		
	}

	public int obtenerCantidadDeMovimientosMaximos(){
		
		return (ContadorDeMovimientos.obtenerInstancia().obtenerCantidadDeMovimientosMaximos());
		
	}
	
	public Ciudad obtenerCiudad(){
		
		return ciudad;
	}
	
	public boolean juegoTerminado(){
		
		return (this.vehiculo.llegoALaMeta());
		
	}
	
	protected abstract void setPuntajeFinalEnELJugador();
	
	public void controlarMovimientos() {
		
		if((ContadorDeMovimientos.obtenerInstancia().obtenerCantidadDeMovimientosRestantes()) <= 0) {
						
			this.vehiculo.finalizarRecorrido();
			
			this.setPuntajeFinalEnELJugador();
		}
	}
	
	public void moverVehiculoEnDireccionDerecha() {
		
	  this.vehiculo.establecerDireccion(new Derecha());
		
	  if (this.vehiculo.puedeAvanzar()) {
		
		Posicion posicionActualVehiculo = this.vehiculo.obtenerPosicion();
		Posicion posicionSiguienteVehiculo;
		
		Bandera unaBandera;
		
		Obstaculo unObstaculo;
		
		Sorpresa unaSorpresa;
		
		unObstaculo = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleDerecha().getObstaculo();
		
		unaSorpresa = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleDerecha().getSorpresa();
		
		this.vehiculo.avanzar();
		
		posicionSiguienteVehiculo = this.vehiculo.obtenerPosicion();
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unaSorpresa);
				this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleDerecha().vaciarSorpresa();
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoLaSorpresaException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unObstaculo);
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoAlObstaculoException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}
		
		if (!(posicionActualVehiculo.igualdadDePosicion(posicionSiguienteVehiculo))){
			
			try{
				
				try{
					unaBandera = this.ciudad.obtenerCruceEnLaPosicion(posicionSiguienteVehiculo).getBandera();
					this.vehiculo.interceptarA(unaBandera);
					
					}
				
					catch(NoConozcoAlVehiculoException miExcepcion){
					
						System.out.println(miExcepcion.toString());
					
					}
						
				}
			
			catch(NoConozcoLaBanderaException miExcepcion){
				
				System.out.println(miExcepcion.toString());
			
			}
			
		}
		
		this.controlarMovimientos();
	  }
	}
	
	public void moverVehiculoEnDireccionIzquierda() {
		
	  this.vehiculo.establecerDireccion(new Izquierda());
      
	  if (this.vehiculo.puedeAvanzar()) {
		  
		Posicion posicionActualVehiculo = this.vehiculo.obtenerPosicion();
	    Posicion posicionSiguienteVehiculo;
		
		Bandera unaBandera;
		
		Obstaculo unObstaculo;
		
		Sorpresa unaSorpresa;
		
		unObstaculo = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleIzquierda().getObstaculo();
		
		unaSorpresa = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleIzquierda().getSorpresa();
				
		this.vehiculo.avanzar();
		
		posicionSiguienteVehiculo = this.vehiculo.obtenerPosicion();
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unaSorpresa);
				this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleIzquierda().vaciarSorpresa();
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoLaSorpresaException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unObstaculo);
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoAlObstaculoException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}	
		
		if (!(posicionActualVehiculo.igualdadDePosicion(posicionSiguienteVehiculo))){
			
			try{
				
				try{
					
					unaBandera = this.ciudad.obtenerCruceEnLaPosicion(posicionSiguienteVehiculo).getBandera();
					this.vehiculo.interceptarA(unaBandera);
					
					}
				
					catch(NoConozcoAlVehiculoException miExcepcion){
					
						System.out.println(miExcepcion.toString());
					
					}
						
				}
			
			catch(NoConozcoLaBanderaException miExcepcion){
				
				System.out.println(miExcepcion.toString());
			
			}
			
		}
		
		this.controlarMovimientos();
	  }
	}
	
	public void moverVehiculoEnDireccionArriba() {
		
	  this.vehiculo.establecerDireccion(new Arriba());
		
	  if (this.vehiculo.puedeAvanzar()) {
		
		Posicion posicionActualVehiculo = this.vehiculo.obtenerPosicion();
		Posicion posicionSiguienteVehiculo;
		  
		Bandera unaBandera;
		
		Obstaculo unObstaculo;
		
		Sorpresa unaSorpresa;
		
		unObstaculo = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleArriba().getObstaculo();
		
		unaSorpresa = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleArriba().getSorpresa();
				
		this.vehiculo.avanzar();
		
		posicionSiguienteVehiculo = this.vehiculo.obtenerPosicion();
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unaSorpresa);
				this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleArriba().vaciarSorpresa();
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoLaSorpresaException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unObstaculo);
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoAlObstaculoException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}	
		
		if (!(posicionActualVehiculo.igualdadDePosicion(posicionSiguienteVehiculo))){
			
			try{
				
				try{
					
					unaBandera = this.ciudad.obtenerCruceEnLaPosicion(posicionSiguienteVehiculo).getBandera();
					this.vehiculo.interceptarA(unaBandera);
					
					}
				
					catch(NoConozcoAlVehiculoException miExcepcion){
					
						System.out.println(miExcepcion.toString());
					
					}
						
				}
			
			catch(NoConozcoLaBanderaException miExcepcion){
				
				System.out.println(miExcepcion.toString());
			
			}
			
		}
		
		this.controlarMovimientos();
	  }
	}
	
	public void moverVehiculoEnDireccionAbajo() {
		
	  this.vehiculo.establecerDireccion(new Abajo());
		
	  if (this.vehiculo.puedeAvanzar()) {
		  
		Posicion posicionActualVehiculo = this.vehiculo.obtenerPosicion();
		Posicion posicionSiguienteVehiculo;
		
		Bandera unaBandera;
		
		Obstaculo unObstaculo;
		
		Sorpresa unaSorpresa;
		
		unObstaculo = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleAbajo().getObstaculo();
		
		unaSorpresa = this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleAbajo().getSorpresa();
				
		this.vehiculo.avanzar();
		
		posicionSiguienteVehiculo = this.vehiculo.obtenerPosicion();
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unaSorpresa);
				this.ciudad.obtenerCruceEnLaPosicion(posicionActualVehiculo).getCalleAbajo().vaciarSorpresa();
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoLaSorpresaException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}
		
		try{
			
			try{
				
				this.vehiculo.interceptarA(unObstaculo);
				
				}
			
				catch(NoConozcoAlVehiculoException miExcepcion){
				
					System.out.println(miExcepcion.toString());
				
				}
					
			}
		
		catch(NoConozcoAlObstaculoException miExcepcion){
			
			System.out.println(miExcepcion.toString());
		
		}	
		
		if (!(posicionActualVehiculo.igualdadDePosicion(posicionSiguienteVehiculo))){
			
			try{
				
				try{
					
					unaBandera = this.ciudad.obtenerCruceEnLaPosicion(posicionSiguienteVehiculo).getBandera();
					this.vehiculo.interceptarA(unaBandera);
					
					}
				
					catch(NoConozcoAlVehiculoException miExcepcion){
					
						System.out.println(miExcepcion.toString());
					
					}
						
				}
			
			catch(NoConozcoLaBanderaException miExcepcion){
				
				System.out.println(miExcepcion.toString());
			
			}
			
		}
		
		this.controlarMovimientos();
	  }
	}

}
